﻿// (c) Copyright Fernando Cerqueira.
// This source is subject to the Microsoft Public License (Ms-PL).
// Please see http://go.microsoft.com/fwlink/?LinkID=131993 for details.
// All other rights reserved.

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Runtime.Serialization;
using System.Text;
using System.Xml;

// ReSharper disable CheckNamespace
namespace WindowsPhoneCommands
// ReSharper restore CheckNamespace
{
    public static class InspectorDataContractSerializer
    {
        public static Dictionary<string,object> Read(string fileName)
        {
            var assembliesTypes = new List<AssembliesTypes>();
            var listKno = new List<Type>();
            var origdic = string.Empty;

            using (var storageFileStream = new FileStream(fileName, FileMode.Open))
            {

                using (var streamReader = new StreamReader(storageFileStream))
                {
                    if (storageFileStream.Length > 0)
                    {
                        try
                        {
                            var str = streamReader.ReadLine();
                            if (str != null)
                            {
                                foreach (var typeName in str.Split(new char[1]))
                                {
                                    Type type = Type.GetType(typeName, false);
                                    if (type != null)
                                    {
                                        assembliesTypes.Add(new AssembliesTypes { Type = type, Name = typeName, KnownType = true });
                                        listKno.Add(type);
                                    }
                                    else
                                    {
                                        assembliesTypes.Add(new AssembliesTypes { Type = null, Name = typeName, KnownType = false });
                                    }
                                }
                                storageFileStream.Position = str.Length + Environment.NewLine.Length;
                            }
                            origdic = streamReader.ReadToEnd();
                        }
                        // ReSharper disable EmptyGeneralCatchClause
                        catch
                        // ReSharper restore EmptyGeneralCatchClause
                        {
                        }
                    }
                }
            }

            //SPLIT ELEMENTS
            var elements = new List<string>();
            var posend = origdic.LastIndexOf("<ArrayOfKeyValueOfstringanyType", StringComparison.Ordinal);
            if (posend >= 0)
            {
                origdic = origdic.Substring(posend + "<ArrayOfKeyValueOfstringanyType".Length);
            }
            posend = origdic.IndexOf("</KeyValueOfstringanyType>", StringComparison.Ordinal);
            while (posend >= 0)
            {
                var posini = origdic.IndexOf("<KeyValueOfstringanyType>", StringComparison.Ordinal);
                elements.Add(origdic.Substring(posini + "<KeyValueOfstringanyType>".Length, posend - (posini + "<KeyValueOfstringanyType>".Length)));
                origdic = origdic.Substring(posend + +"</KeyValueOfstringanyType>".Length);
                posend = origdic.IndexOf("</KeyValueOfstringanyType>", StringComparison.Ordinal);
            }
            //try Deserialize elements
            var result = new Dictionary<string,object>();
            foreach (var item in elements)
	        {
                var strser = CreateDataContractSerializer(item);
	            var xdoc = new XmlDocument {InnerXml = strser};
	            try
                {
                    var settings = (Dictionary<string, object>)new DataContractSerializer(typeof(Dictionary<string, object>), listKno).ReadObject(new MemoryStream(Encoding.UTF8.GetBytes(strser)));
                    result.Add(settings.Keys.ToArray()[0], settings.Values.ToArray()[0]);
                }
                catch
                {
                    var knode= xdoc.GetElementsByTagName("Key");
                    var vnode = xdoc.GetElementsByTagName("Value");
                    var localname = string.Empty;
                    var xmlAttributeCollection = vnode[0].Attributes;
                    if (xmlAttributeCollection != null)
                        foreach (XmlAttribute att in xmlAttributeCollection.Cast<XmlAttribute>().Where(att => att.Name.ToLower() == "i:type"))
                        {
                            localname = att.Value;
                            var pos = localname.IndexOf(":", StringComparison.Ordinal);
                            if (pos >= 0)
                            {
                                localname = localname.Substring(pos + 1);
                            }
                            break;
                        }

                    result.Add(knode[0].InnerXml + "|" + localname, vnode[0]);
                }
	        }
            return result;
        }

        private static string CreateDataContractSerializer(string elem)
        {
            var sb = new StringBuilder();
            sb.AppendLine("<ArrayOfKeyValueOfstringanyType xmlns:i=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns=\"http://schemas.microsoft.com/2003/10/Serialization/Arrays\">");
            sb.AppendLine("<KeyValueOfstringanyType>");
            sb.Append(elem);
            sb.AppendLine("</KeyValueOfstringanyType>");
            sb.AppendLine("</ArrayOfKeyValueOfstringanyType>");
            return sb.ToString();
        }
    }
}
